import { createMap } from "../../map/index.js";
import { LatLng, toLatLng } from "../../geo/LatLng.js";
import { Bounds } from "../../geometry/Bounds.js";
import { Point, toPoint } from "../../geometry/Point.js";

import { tileLayer } from "./TileLayer.js";
import Map from "../../map/Map.js";

import {
  LatLongToTileXY,
  TileXYToLatLong,
  LatLongToMeterXY,
  MetersToPixelXY,
  PixelXYToTileXY,
} from "../../core/Util.js";

export class GridLayer {
  options = {
    // 网格中瓷砖的宽度和高度。如果宽度和高度相等，请使用数字，否则使用“L.point（宽度，高度）”。
    tileSize: 256,
    opacity: 1,
    // updateWhenIdle: Browser.mobile,

    updateWhenZooming: true,
    updateInterval: 200,
    zIndex: 1,
    bounds: null,
    minZoom: 0,
    maxZoom: undefined,
    maxNativeZoom: undefined,
    minNativeZoom: undefined,
    noWrap: false,
    pane: "tilePane",
    className: "",
    keepBuffer: 2, // 这个是保证图片最小状态有4个图片，一个大正方形
  };
  _tiles = {};
  origin;
  office = toPoint(0, 0);
  imgs = [];
  constructor(map, lat, lng, zoom, ctx) {
    this._tileZoom = zoom;
    this._ctx = ctx;
    // var map = createMap("app", {}).setView([lat, lng], this._tileZoom);
    this._map = map;

    this.origin = map.getPixelOrigin();
    this._lat = lat;
    this._lng = lng;

    // console.log(LatLongToTileXY(lng, lat, zoom));

    // 角度转弧度
    const angleToRad = (angle) => {
      return angle * (Math.PI / 180);
    };

    // 弧度转角度
    const radToAngle = (rad) => {
      return rad * (180 / Math.PI);
    };

    // 地球半径
    const EARTH_RAD = 6378137;

    // 4326转3857
    const lngLat2Mercator = (lng, lat) => {
      // 经度先转弧度，然后因为 弧度 = 弧长 / 半径 ，得到弧长为 弧长 = 弧度 * 半径
      let x = angleToRad(lng) * EARTH_RAD;
      // 纬度先转弧度
      let rad = angleToRad(lat);
      // 下面我就看不懂了，各位随意。。。
      let sin = Math.sin(rad);
      let y = (EARTH_RAD / 2) * Math.log((1 + sin) / (1 - sin));
      return [x, y];
    };

    const aa = lngLat2Mercator(lng, lat);

    // 3857转4326
    const mercatorTolnglat = (x, y) => {
      let lng = radToAngle(x) / EARTH_RAD;
      let lat = radToAngle(
        2 * Math.atan(Math.exp(y / EARTH_RAD)) - Math.PI / 2
      );
      return [lng, lat];
    };
    // console.log("转为墨卡托" + aa, mercatorTolnglat(aa[0], aa[1]));







    









// const EARTH_RAD = 6378137;

// 地球周长
const EARTH_PERIMETER = 2 * Math.PI * EARTH_RAD
// 瓦片像素
const TILE_SIZE = 256

// 获取某一层级下的分辨率
const getResolution = (n) => {
    const tileNums = Math.pow(2, n)
    const tileTotalPx = tileNums * TILE_SIZE
    return EARTH_PERIMETER / tileTotalPx
    }
  

const getTileRowAndCol = (x, y, z) => {
  x += EARTH_PERIMETER / 2; // ++
  y = EARTH_PERIMETER / 2 - y; // ++
  let resolution = getResolution(z);
  let row = Math.floor(x / resolution / TILE_SIZE);
  let col = Math.floor(y / resolution / TILE_SIZE);
  return [row, col];
};

    // console.log("ddddd", getTileRowAndCol(aa[0], aa[1],zoom));








    


    // const m = LatLongToMeterXY(lng, lat);

    // const b = MetersToPixelXY(m.mx, m.my, this._tileZoom);

    // const c = PixelXYToTileXY(b.px, b.py);

    this._update(toLatLng(lat, lng));

    setTimeout(() => {
      this.drawPoint({
        ctx: this._ctx,
        coordinate: [25.047944995715422, 102.73129657902908],
      });
    }, 1);
  }
  moveTo(x) {
    this.office = x;
    this._ctx.clearRect(
      0,
      0,
      this._map._container.width,
      this._map._container.height
    );
    for (let i = 0; i < this.imgs.length; i++) {
      this._addTile(this.imgs[i]);
    }
  }

  drawPoint({ ctx, coordinate, color = "#ff4f02", radius = 10 }) {
    const pos = this._map.latLngToLayerPoint(
      toLatLng(coordinate[0], coordinate[1])
    );
    ctx.beginPath();
    ctx.fillStyle = color;
    ctx.arc(
      this.office.x + pos.x,
      this.office.y + pos.y,
      radius,
      0,
      2 * Math.PI
    );
    ctx.fill();
  }

  _update(center) {
    // _获取平铺像素边界
    const pixelBounds = this._getTiledPixelBounds(center),
      // 获取在墨卡托中的范围
      tileRange = this._pxBoundsToTileRange(pixelBounds),
      // 中心点的图片坐标
      tileCenter = tileRange.getCenter(),
      queue = [],
      margin = this.options.keepBuffer,
      noPruneRange = new Bounds(
        tileRange.getBottomLeft().subtract([margin, -margin]),
        tileRange.getTopRight().add([margin, -margin])
      );

    for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
      for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
        const coords = new Point(i, j);
        coords.z = this._tileZoom;
        const tile = this._tiles[this._tileCoordsToKey(coords)];
        if (tile) {
          tile.current = true;
        } else {
          queue.push(coords);
        }
      }
    }

    queue.sort((a, b) => a.distanceTo(tileCenter) - b.distanceTo(tileCenter));

    if (queue.length !== 0) {
      if (!this._loading) {
        this._loading = true;
      }

      queue.forEach((item) => {
        this.loadImages(item, (e) => {
          // 因为该方法鼠标移动一个像素就会执行一次，所以这个数组会获取比较多的次数，
          // 通过isf，判断一下总数组里边是否有这个数组了，
          // 没有才去绘制图片，才在imgs里增加子集
          const isf = this.imgs.some(
            (it) => it.coords.x === item.x && it.coords.y === item.y
          );
          if (!isf) {
            this.imgs.push(e);
            this._addTile(e);
          }
        });
      });
    }

    this.drawPoint({
      ctx: this._ctx,
      coordinate: [24.912, 102.84142],
    });
  }

  loadImages(sources, callback) {
    var image = new Image();
    const tLayer = new tileLayer();
    const url = tLayer.getTileUrl(sources);
    image.src = url;
    image.onload = () => {
      const obj = {
        image: image,
        coords: sources,
      };
      callback(obj);
    };
  }

  _addTile(tile_coords) {

    const tilePos = this._getTilePos(tile_coords.coords);
    this._ctx.drawImage(
      tile_coords.image,
      tilePos.x + this.office.x,
      tilePos.y + this.office.y,
      256,
      256
    );
  }

  _tileCoordsToKey(coords) {
    return `${coords.x}:${coords.y}:${coords.z}`;
  }
  _pxBoundsToTileRange(bounds) {
    const tileSize = this.getTileSize();
    return new Bounds(
      bounds.min.unscaleBy(tileSize).floor(),
      bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1])
    );
  }

  _getTilePos(coords) {
    const tileSize = this.getTileSize();
    // 当前的瓦片的坐标 乘以 每块瓦片的大小，得出x,y方向的实际像素
    const fact = coords.scaleBy(this.getTileSize());
    // 瓦片实际像素减去 画布左上角对应的像素，得到的值就是这个瓦片显示的实际XY
    // tip:像素元点是中心点变为像素后，减去画布的长宽像素的一般，即画布左上角是 origin
    const point = fact.subtract(this.origin);
    return point;
  }
  getTileSize() {
    const s = this.options.tileSize;
    return s instanceof Point ? s : new Point(s, s);
  }

  /**
   * 获取平铺像素边界
   * @param {*} center
   * @returns
   */
  _getTiledPixelBounds(center) {

    const map = this._map,
      scale = 1,
      pixelCenter = map.project(center, this._tileZoom).floor(),
      halfSize = map.getSize().divideBy(scale * 2);
    

    //



    return new Bounds(
      pixelCenter.subtract(halfSize),
      pixelCenter.add(halfSize)
    );
  }

  _isValidTile(coords) {
    const crs = this._map.options.crs;

    if (!crs.infinite) {
      // don't load tile if it's out of bounds and not wrapped
      const bounds = this._globalTileRange;
      if (
        (!crs.wrapLng &&
          (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||
        (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))
      ) {
        return false;
      }
    }

    if (!this.options.bounds) {
      return true;
    }

    // don't load tile if it doesn't intersect the bounds in options
    const tileBounds = this._tileCoordsToBounds(coords);
    return latLngBounds(this.options.bounds).overlaps(tileBounds);
  }
  _tileCoordsToBounds(coords) {
    const bp = this._tileCoordsToNwSe(coords);
    let bounds = new LatLngBounds(bp[0], bp[1]);

    if (!this.options.noWrap) {
      bounds = this._map.wrapLatLngBounds(bounds);
    }
    return bounds;
  }
}
